// noinspection NonAsciiCharacters

import type {
  ElementCategoriesConfig,
  ElementCategoriesItemConfig,
} from '../../../types/constants'
import type { PlatformTypeValue } from '../../../types/interfaces'
import type { ConfigValidationResult, ConfigValidationStats } from './types'
import { ToolKit } from '../../../lib/utils/toolkit'
import {
  APP_CONFIG,
  createElementConfig,
  logger,
} from '../../../types/constants'
import { SYMBOLS } from '../../../types/interfaces'
import { WebElement } from '../../config/web_element'

/**
 * 配置检测服务 - 负责验证平台配置的完整性和正确性
 */
export class ConfigValidatorService {
  private readonly name: string = 'ConfigValidatorService'
  private static instance: ConfigValidatorService
  private readonly webElement: WebElement = WebElement.getInstance()
  private readonly platformConfigs: ElementCategoriesConfig = this.webElement.getConfigs()
  private validationErrors: string[] = []
  private validationWarnings: string[] = []

  /**
   * 获取单例实例
   */
  public static getInstance(): ConfigValidatorService {
    if (!ConfigValidatorService.instance) {
      ConfigValidatorService.instance = new ConfigValidatorService()
    }
    return ConfigValidatorService.instance
  }

  /**
   * 验证所有配置
   */
  validateAllConfigs(): ConfigValidationResult {
    if (!APP_CONFIG.validateConfig) {
      return {
        isValid: false,
        errors: [],
        warnings: [],
        timestamp: new Date().toISOString(),
      }
    }

    logger.info(`[${this.name}] ${SYMBOLS.UI.SEARCH} 开始验证元素隐藏规则...`)

    try {
      // 1. 验证平台配置分类重复性
      this.validatePlatformConfigCategories()

      const isValid = this.validationErrors.length === 0

      if (isValid) {
        logger.info(`[${this.name}] 所有配置验证通过`)
        if (this.validationWarnings.length > 0) {
          logger.warn(`[${this.name}] 发现警告:`, this.validationWarnings)
        }
      }
      else {
        logger.error(`[${this.name}] 配置验证失败`, this.validationErrors)
      }

      return {
        isValid,
        errors: [...this.validationErrors],
        warnings: [...this.validationWarnings],
        timestamp: new Date().toISOString(),
      }
    }
    catch (error) {
      logger.error(`[${this.name}] 配置验证过程异常:`, error)
      return {
        isValid: false,
        errors: [`验证过程异常: ${error}`],
        warnings: [],
        timestamp: new Date().toISOString(),
      }
    }
  }

  /**
   * 验证平台配置分类重复性
   */
  private validatePlatformConfigCategories(): void {
    const platformKeys = Object.keys(this.platformConfigs)
    const uniqueKeys = new Set(platformKeys)

    // 检查平台键重复
    if (platformKeys.length !== uniqueKeys.size) {
      this.validationErrors.push(`${SYMBOLS.STATUS.ERROR} 平台配置中存在重复的分类键`)

      // 找出重复的键
      const duplicateKeys = ToolKit.config.findDuplicateItems(platformKeys)
      duplicateKeys.forEach((key) => {
        this.validationErrors.push(`${SYMBOLS.UI.SEARCH} 重复平台: ${key}`)
      })
    }

    // 使用表格输出平台统计信息
    const platformTableData = platformKeys.map(platform => ({
      平台名称: platform,
      配置数量: Object.keys(this.platformConfigs[platform] || {}).length,
      状态: uniqueKeys.has(platform) ? `${SYMBOLS.STATUS.SUCCESS} 唯一` : `${SYMBOLS.STATUS.ERROR} 重复`,
    }))
      .sort((a, b) => b.配置数量 - a.配置数量)

    logger.table(`[${this.name}] ${SYMBOLS.UI.CHART} 平台配置统计`, platformTableData)

    // 按配置数量升序执行平台验证（配置少的先执行，便于快速发现问题）
    const sortedPlatforms = platformKeys
      .map(platform => ({
        platform,
        configCount: Object.keys(this.platformConfigs[platform] || {}).length,
      }))
      .sort((a, b) => a.configCount - b.configCount) // 按配置数量升序排序

    // 检查每个平台配置内部的键重复
    sortedPlatforms.forEach(({ platform }) => {
      this.validatePlatformConfigCompleteness(platform, this.platformConfigs[platform])
    })
  }

  /**
   * 验证平台内部配置键
   */
  private validatePlatformConfigCompleteness(platform: PlatformTypeValue, config: ElementCategoriesItemConfig): void {
    if (!config || typeof config !== 'object') {
      this.validationErrors.push(`${SYMBOLS.STATUS.ERROR} 平台 ${platform} 配置为空或格式错误`)
      return
    }

    const configKeys = Object.keys(config)
    const uniqueKeys = new Set(configKeys)

    // 1. 验证配置键重复性
    this.validateConfigKeysUniqueness(platform, configKeys, uniqueKeys)

    // 2. 验证配置内容完整性
    this.validateConfigContentCompleteness(platform, config, configKeys, uniqueKeys)

    // 3. 输出平台内部配置详情
    // this.printConfigDetail(platform, config, configKeys, uniqueKeys)
  }

  /**
   * 验证配置键唯一性
   */
  private validateConfigKeysUniqueness(platform: PlatformTypeValue, configKeys: string[], uniqueKeys: Set<string>): void {
    // 检查内部键重复
    if (configKeys.length === uniqueKeys.size)
      return

    this.validationErrors.push(`${SYMBOLS.STATUS.ERROR} 平台 ${platform} 配置中存在重复的键`)

    const duplicateKeys = ToolKit.config.findDuplicateItems(configKeys)
    duplicateKeys.forEach((key) => {
      this.validationErrors.push(`${SYMBOLS.UI.SEARCH} 重复键: ${platform}.${key}`)
    })

    // 使用表格输出重复键详情
    const duplicateTableData = duplicateKeys.map(key => ({
      平台: platform,
      重复键: key,
      出现次数: configKeys.filter(k => k === key).length,
    }))
      .sort((a, b) => b.出现次数 - a.出现次数)

    logger.table(`[${this.name}] ${SYMBOLS.UI.SEARCH} 平台 ${platform} 重复键详情`, duplicateTableData)
  }

  /**
   * 验证配置内容完整性
   */
  private validateConfigContentCompleteness(platform: PlatformTypeValue, config: ElementCategoriesItemConfig, configKeys: string[], uniqueKeys: Set<string>): void {
    const validationResults: Array<{
      平台: string
      配置键: string
      选择器: string
      中文名: string
      英文名: string
      类型: string
      状态: string
      问题描述: string
      严重程度: string
      排序权重: number
    }> = []

    configKeys.forEach((key) => {
      const elementConfig = config[key]
      const processedConfig = createElementConfig(key, elementConfig)

      // 验证单个配置项的完整性
      const validationResult = this.validateSingleConfigCompleteness(platform, key, processedConfig, uniqueKeys)
      validationResults.push(validationResult)
    })

    // 输出验证结果表格
    this.outputValidationResultsTable(platform, validationResults)
  }

  /**
   * 验证单个配置项的完整性
   */
  private validateSingleConfigCompleteness(platform: string, key: string, processedConfig: any, uniqueKeys: Set<string>): any {
    const expectedSelectorType = ToolKit.ui.element.detectSelectorType(processedConfig?.selector)
    const selectorType = processedConfig?.selectorType

    // 检查必需字段
    const hasSelector = !!processedConfig?.selector
    const hasSelectorType = !!processedConfig?.selectorType
    const hasNameZh = !!processedConfig?.nameZh
    const hasNameEn = !!processedConfig?.nameEn

    // 检查字段有效性
    const selectorValid = hasSelector && processedConfig.selector.trim().length > 0
    const selectorTypeRequired = hasSelectorType
    const selectorTypeValid = expectedSelectorType === selectorType

    const nameZhValid = hasNameZh && this.isValidChineseName(processedConfig.nameZh)
    const nameEnValid = hasNameEn && this.isValidEnglishName(processedConfig.nameEn)
    const isUnique = uniqueKeys.has(key)

    // 计算问题严重程度
    const hasCriticalError = !selectorValid || !selectorTypeRequired || !selectorTypeValid || !isUnique
    const hasError = !hasNameZh || !hasNameEn
    const hasWarning = !nameZhValid || !nameEnValid || (processedConfig?.selector?.length > 500)

    // 生成问题描述
    const issues: string[] = []
    if (!isUnique)
      issues.push('键重复')
    if (!selectorValid)
      issues.push('选择器无效')
    if (!selectorTypeRequired)
      issues.push('类型缺失')
    if (!selectorTypeValid)
      issues.push('类型错误')
    if (!hasNameZh)
      issues.push('缺少中文名')
    if (!hasNameEn)
      issues.push('缺少英文名')
    if (!nameZhValid && hasNameZh)
      issues.push('中文名不规范')
    if (!nameEnValid && hasNameEn)
      issues.push('英文名不规范')
    if (processedConfig?.selector?.length > 500)
      issues.push('选择器过长')

    const 严重程度 = hasCriticalError
      ? `${SYMBOLS.STATUS.ERROR} 严重错误`
      : hasError
        ? `${SYMBOLS.STATUS.ERROR} 错误`
        : hasWarning
          ? `${SYMBOLS.STATUS.WARNING} 警告`
          : `${SYMBOLS.STATUS.SUCCESS} 正常`
    const 状态
      = isUnique
        ? (hasCriticalError
            ? `${SYMBOLS.STATUS.ERROR} 错误`
            : hasError
              ? `${SYMBOLS.STATUS.ERROR} 不完整`
              : hasWarning
                ? `${SYMBOLS.STATUS.WARNING} 警告`
                : `${SYMBOLS.STATUS.SUCCESS} 正常`)
        : `${SYMBOLS.STATUS.ERROR} 重复`

    // 计算排序权重（严重程度越高，权重越大）
    const 排序权重 = hasCriticalError ? 4 : hasError ? 3 : hasWarning ? 2 : isUnique ? 1 : 0

    return {
      平台: platform,
      配置键: key,
      选择器: processedConfig?.selector ? ToolKit.string.truncate(processedConfig.selector, 30) : `${SYMBOLS.STATUS.ERROR} 缺失`,
      中文名: processedConfig?.nameZh ? processedConfig.nameZh : `${SYMBOLS.STATUS.ERROR} 缺失`,
      英文名: processedConfig?.nameEn ? processedConfig.nameEn : `${SYMBOLS.STATUS.ERROR} 缺失`,
      类型: selectorType || `${SYMBOLS.STATUS.ERROR} 缺失`,
      实际类型: expectedSelectorType || `${SYMBOLS.STATUS.ERROR} 缺失`,
      状态,
      问题描述: issues.length > 0 ? issues.join('，') : '无',
      严重程度,
      排序权重,
    }
  }

  /**
   * 输出验证结果表格
   */
  private outputValidationResultsTable(platform: string, validationResults: any[]): void {
    // 按严重程度排序
    const sortedResults = validationResults
      .sort((a, b) => b.排序权重 - a.排序权重)

    // 统计验证结果
    const totalConfigs = sortedResults.length
    const criticalErrors = sortedResults.filter(r => r.严重程度 === `${SYMBOLS.STATUS.ERROR} 严重错误`).length
    const errors = sortedResults.filter(r => r.严重程度 === `${SYMBOLS.STATUS.ERROR} 错误`).length
    const warnings = sortedResults.filter(r => r.严重程度 === `${SYMBOLS.STATUS.WARNING} 警告`).length
    const normal = totalConfigs - criticalErrors - errors - warnings

    const healthPercent: number = totalConfigs ? Math.round(normal / totalConfigs * 100) : 0
    let healthContent: string = 'NA'

    if (healthPercent === 100) {
      healthContent = `${SYMBOLS.STATUS.SUCCESS} ${healthPercent}%`
    }
    else if (healthPercent > 0) {
      healthContent = `${SYMBOLS.STATUS.WARNING} ${healthPercent}%`
    }

    // 输出统计信息
    const statsTable = [{
      平台: platform,
      总配置数: totalConfigs,
      严重错误: criticalErrors,
      一般错误: errors,
      警告: warnings,
      正常: normal,
      健康度: healthContent,
    }]

    // 只输出有问题的配置
    const problematicConfigs = sortedResults
      .filter(r => r.排序权重 > 1) // 过滤出警告及以上级别的问题
      .map(({ 排序权重, ...rest }) => rest) // 移除排序权重字段

    if (problematicConfigs.length > 0) {
      logger.table(`[${this.name}] ${SYMBOLS.UI.CHART} 平台 ${platform} 配置健康度统计`, statsTable)
      logger.table(`[${this.name}] ${SYMBOLS.UI.SEARCH} 平台 ${platform} 问题配置详情`, problematicConfigs)
    }
    else {
      logger.info(`[${this.name}] ${SYMBOLS.STATUS.SUCCESS} 平台 ${platform} 所有配置验证通过`)
    }

    // 记录验证错误到全局错误列表
    sortedResults
      .filter(r => r.排序权重 >= 3) // 只记录错误及以上级别
      .forEach((result) => {
        if (result.排序权重 >= 4) {
          this.validationErrors.push(`${SYMBOLS.STATUS.ERROR} ${result.平台}.${result.配置键}: ${result.问题描述}`)
        }
        else if (result.排序权重 >= 3) {
          this.validationErrors.push(`${SYMBOLS.STATUS.ERROR} ${result.平台}.${result.配置键}: ${result.问题描述}`)
        }
      })
  }

  /**
   * 输出平台内部配置详情
   */
  printConfigDetail(platform: PlatformTypeValue, config: ElementCategoriesItemConfig, configKeys: string[], uniqueKeys: Set<string>): void {
    const internalConfigTableData = configKeys.map((key) => {
      const elementConfig = config[key]
      const processedConfig = createElementConfig(key, elementConfig)

      const hasError = !processedConfig?.selector || !processedConfig?.selectorType
      const hasWarning = processedConfig?.selector?.length > 500

      return {
        平台: platform,
        配置键: key,
        选择器: processedConfig?.selector ? ToolKit.string.truncate(processedConfig.selector, 30) : `${SYMBOLS.STATUS.ERROR} 缺失`,
        中文名: processedConfig?.nameZh ? processedConfig.nameZh : `${SYMBOLS.STATUS.ERROR} 缺失`,
        英文名: processedConfig?.nameEn ? processedConfig.nameEn : `${SYMBOLS.STATUS.ERROR} 缺失`,
        类型: processedConfig?.selectorType || `${SYMBOLS.STATUS.ERROR} 缺失`,
        状态: uniqueKeys.has(key) ? `${SYMBOLS.STATUS.SUCCESS} 唯一` : `${SYMBOLS.STATUS.ERROR} 重复`,
        状态优先级: hasError ? 3 : !uniqueKeys.has(key) ? 2 : hasWarning ? 1 : 0, // 用于排序
      }
    })
      // 排序： 状态优先级 > 类型 > 配置键
      .sort((a, b) => {
        if (b.状态优先级 === a.状态优先级) {
          if (b.类型 === a.类型) {
            return a.配置键.localeCompare(b.配置键)
          }

          return b.类型.localeCompare(a.类型)
        }

        return b.状态优先级 - a.状态优先级
      })

    // 移除状态优先级字段，只用于排序
    const finalTableData = internalConfigTableData.map(({ 状态优先级, ...rest }) => rest)

    logger.table(`[${this.name}] ${SYMBOLS.NETWORK.GLOBE} 平台 ${platform} 规则配置详情`, finalTableData)
  }

  /**
   * 验证中文名格式
   */
  private isValidChineseName(name: string): boolean {
    if (!name || name.trim() === '')
      return false

    // 中文名应该包含中文字符，长度合理
    const chineseCharCount = (name.match(/[\u4E00-\u9FA5]/g) || []).length
    return chineseCharCount > 0 && chineseCharCount <= 20 && name.length <= 50
  }

  /**
   * 验证英文名格式
   */
  private isValidEnglishName(name: string): boolean {
    if (!name || name.trim() === '')
      return false

    // 英文名应该符合标识符规范
    return /^[a-z][a-z0-9]*$/i.test(name) && name.length <= 50
  }

  /**
   * 获取验证统计信息
   */
  getValidationStats(): ConfigValidationStats {
    const allConfigs = this.webElement.getSelectors({ ignorePlatformCheck: true })
    const platformCount = Object.keys(this.platformConfigs).length
    const totalConfigCount = allConfigs.length

    return {
      platformCount,
      totalConfigCount,
      errorCount: this.validationErrors.length,
      warningCount: this.validationWarnings.length,
      lastValidation: new Date().toISOString(),
    }
  }

  /**
   * 清空验证结果
   */
  clearValidationResults(): void {
    this.validationErrors = []
    this.validationWarnings = []
    logger.info(`[${this.name}] ${SYMBOLS.OTHERS.CLEAR} 验证结果已清空`)
  }
}
